import axios from 'axios';
import { Message } from 'element-ui';
import $store from '@/store';
import $router from '@/router';
import { $rp } from '@/utils/constants';
import base from '@/api/base';

const tokenError = {
  110002: '用户token错误，请重新登录',
  110003: '用户token已过期，请重新登录',
  110008: '请登录后继续',
};

const noRejectMsg = [
  'Network Error',
  'Request failed with status code 500',
];

const otherApi = [
  'https://up-z2.qiniup.com',
  'https://api.yozocloud.cn/getPreview',
];

axios.interceptors.request.use( // 发送前拦截
  (config) => {
    Object.assign(config, {
      timeout: 30000, // 30s 超时
    });
    Object.assign(config.headers, {
      come_from: 'web', // web wechat
    });
    if (config.url.indexOf(base.sq) !== -1 && $store.state.currentUser.id) { // 用户登录时默认带上用户token
      Object.assign(config.headers, {
        Authorization: $store.state.currentUser.token,
      });
    }
    return config;
  },
);

// 这里与后端约定，只要请求正确，只返回200和5xx，其余所有信息包裹在200里面
axios.interceptors.response.use( // 返回时拦截
  (res) => {
    if (res.status === 200) {
      if (otherApi.includes(res.config.url)) return Promise.resolve(res.data); // 当上传文件到七牛时，直接返回结果
      else if (res.data.code === 0) return Promise.resolve(res.data); // 正确返回数据
      else if (res.data.code in tokenError) { // 当token出问题时
        $store.dispatch('removeCurrentUser'); // 清空当前用户数据
        const currentPath = $router.currentRoute.fullPath;
        const signInPath = `/${$rp.USERS}/${$rp.SIGN_IN}`;
        if (currentPath.indexOf(signInPath) === -1) { // 当不是在注册页面反复跳转时
          $router.push({ // 跳转到登录页
            path: signInPath,
            query: { redirect: currentPath },
          }).catch(err => err);
        }
        Message.error(res.data.msg);
        return Promise.reject(undefined); // 信息已处理，不返回内容
      }
      Message.error(res.data.msg); // 服务器受理但出错，返回的信息会包裹在data里面
      return Promise.reject(res);
    }
    // 状态码不是200，约定中不会出现这种情况，只要代码没写漏
    Message.error(res.statusText || res.data.msg);
    return Promise.reject(res);
  },
  (err) => {
    Message.error('网络错误');
    if (noRejectMsg.includes(err.message)) return Promise.reject(undefined); // 网络错误时不往后报信息
    return Promise.reject(err);
  },
);

export default axios;
